package com.weedsdream.app.colorplate

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.AwaitPointerEventScope
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toOffset
import com.weedsdream.app.colorplate.Axis3.Type.B
import com.weedsdream.app.colorplate.Axis3.Type.G
import com.weedsdream.app.colorplate.Axis3.Type.R
import com.weedsdream.app.colorplate.Axis3.following
import com.weedsdream.app.colorplate.Axis3.pos3
import com.weedsdream.app.colorplate.Axis3.radius
import com.weedsdream.app.colorplate.Axis3.rgb
import com.weedsdream.app.colorplate.Axis3.rgbChange
import com.weedsdream.app.colorplate.Axis3.type
import com.weedsdream.app.function.findIntersection
import com.weedsdream.app.function.pointInPolygon
import kotlin.math.min
import kotlin.math.pow

/**当前取色值*/
var curRGB by mutableStateOf(Color.Black)

/**当前取色位置*/
var curPos by mutableStateOf(IntOffset.Zero)

/**色盘可用*/
private var plateIsOk by mutableStateOf(false)

/**色盘可用区域中心点:单位-像素*/
private var plateCenter = Offset.Zero

/**手势检测区域中心点:单位-像素*/
private var spaceCenter = Offset.Zero

/**色点像素半径*/
internal var pixelPerCP = 6f

/**色盘*/
@Preview(widthDp = 600, heightDp = 350)
@Composable
fun ColorPlate() {
    Box(Modifier.fillMaxSize()) {
        //手势检测
        Spacer(
            Modifier
                .fillMaxSize()
                .onGloballyPositioned {
                    spaceCenter = with(it.size) { Offset(width / 2f, height / 2f) }
                }
                .pointerInput(Unit) { awaitEachGesture { onHandSlide() } })
        //色盘范围
        Box(
            Modifier
                .fillMaxSize(0.8f)
                .align(Alignment.Center)
        ) {
            //获取色盘可用半径
            Spacer(
                Modifier
                    .fillMaxSize()
                    .onGloballyPositioned {
                        if (!plateIsOk) {
                            plateCenter = with(it.size) { Offset(width / 2f, height / 2f) }
                            val plateRadius = min(plateCenter.x, plateCenter.y)//色盘半径
                            initXyRgb(plateRadius)//计算每种颜色对直角坐标的贡献
                            initColorPoints(plateRadius)
                            plateIsOk = true
                        }
                    })
            if (plateIsOk) {
                //绘制色盘
                var orv by remember { mutableIntStateOf(rgbChange) }
                var ogv by remember { mutableIntStateOf(rgbChange) }
                var obv by remember { mutableIntStateOf(rgbChange) }
                val ost = Modifier.offset { with(plateCenter) { IntOffset(x.toInt(), y.toInt()) } }
                Canvas(ost) {
                    if (type == R) if (orv != rgbChange) orv = rgbChange//通过数据变化强制触发UI刷新
                    colorPointsR.forEach {
                        drawCircle(it.show, radius = pixelPerCP, center = it.offset)
                    }
                }
                Canvas(ost) {
                    if (type == G) if (ogv != rgbChange) ogv = rgbChange
                    colorPointsG.forEach {
                        drawCircle(it.show, radius = pixelPerCP, center = it.offset)
                    }
                }
                Canvas(ost) {
                    if (type == B) if (obv != rgbChange) obv = rgbChange
                    colorPointsB.forEach {
                        drawCircle(it.show, radius = pixelPerCP, center = it.offset)
                    }
                }
                Box(ost) {
                    //选中色
                    Spacer(
                        Modifier
                            .offset {
                                curPos - (10.dp)
                                    .toPx()
                                    .toInt()
                                    .let { IntOffset(it, it) }
                            }
                            .clip(CircleShape)
                            .size(20.dp)
                            .background(curRGB))
                    //第三轴点
                    Icon(Icons.Default.Star, null, Modifier
                        .size(20.dp)
                        .onGloballyPositioned { if (radius == 0f) radius = it.size.height / 2f }
                        .offset {
                            IntOffset(
                                (pos3.x - radius).toInt(), (pos3.y - radius).toInt()
                            )
                        }, Color.White
                    )
                }
            }
        }
    }
}

/**正在选取颜色*/
private var chosenColor = false

/**色盘手势检测*/
private suspend fun AwaitPointerEventScope.onHandSlide() {
    while (true) {
        if (!plateIsOk) continue
        val pointers = awaitPointerEvent().changes
        if (pointers[0].pressed) {//手势按下/滑动
            val event = pointers[0]
            val srcPos = event.position - spaceCenter //触摸坐标转中心直角坐标
            val inPlate = pointInPolygon(srcPos, platePeakPoints)//触摸点是否在色盘有效范围内
            //将触摸点转换为有效的色盘中相对中心点坐标
            val pos = if (inPlate) srcPos else findIntersection(srcPos, platePeakPoints)//转色盘有效坐标
            //计算实际位置对应的扇面取色(至少有个参数为0)
            val pColor = offset2color(pos)
            val pr = (pColor.red * 255).toInt()
            val pg = (pColor.green * 255).toInt()
            val pb = (pColor.blue * 255).toInt()
            //分析手势类型
            if (event.previousPressed) {//滑动
                if (following) {//第三轴点正在跟随
                    when (type) {//第三参数值变更
                        R -> Axis3.computeAxis3(pr, 1, 1)
                        G -> Axis3.computeAxis3(1, pg, 1)
                        B -> Axis3.computeAxis3(1, 1, pb)
                        null -> Axis3.computeAxis3(
                            if (pr == 0) 1 else pr, if (pg == 0) 1 else pg, if (pb == 0) 1 else pb
                        )
                    }
                }
            } else {//按下
                if ((pos.x - pos3.x).pow(2) + (pos.y - pos3.y).pow(2) <= radius.pow(2)) {//第三轴点跟随
                    following = true
                } else if (inPlate) {//获取当前触摸值
                    chosenColor = true
                }
            }
            if (chosenColor) {//颜色选择模式，使用当前坐标新颜色
                curRGB = if (type == R && pr == 0) Color(rgb, pg, pb)
                else if (type == G && pg == 0) Color(pr, rgb, pb)
                else if (type == B && pb == 0) Color(pr, pg, rgb)
                else pColor
                curPos = IntOffset(pos.x.toInt(), pos.y.toInt())
            } else if (following) {//第三参数跟随，其它参数保持
                val or = (curRGB.red * 255).toInt()
                val og = (curRGB.green * 255).toInt()
                val ob = (curRGB.blue * 255).toInt()
                val cc = offset2color(curPos.toOffset())//获取已经选择色彩的位置并转换为本应显示的颜色
                curRGB = if (type == R && cc.red == 0f) Color(rgb, og, ob)
                else if (type == G && cc.green == 0f) Color(or, rgb, ob)
                else if (type == B && cc.blue == 0f) Color(or, og, rgb)
                else curRGB
            }
        } else {//手势抬起
            following = false
            chosenColor = false
        }
    }
}




